package com.card.manager.services.impl;

import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

import org.apache.commons.lang.StringUtils;
import org.springframework.security.access.ConfigAttribute;
import org.springframework.security.access.SecurityConfig;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.card.framework.mybatis.mapper.BatchCallBack;
import com.card.framework.mybatis.mapper.MyFrameworkSupperMapper;
import com.card.framework.mybatis.optimist.ModifiedByAnotherUserException;
import com.card.framework.page.model.PageModel;
import com.card.manager.dao.ResourcesMapper;
import com.card.manager.dao.RolesMapper;
import com.card.manager.dao.RolesResourcesMapper;
import com.card.manager.dao.UsersMapper;
import com.card.manager.domain.Resources;
import com.card.manager.domain.ResourcesExample;
import com.card.manager.domain.Roles;
import com.card.manager.domain.RolesExample;
import com.card.manager.domain.RolesExample.Criteria;
import com.card.manager.domain.RolesResources;
import com.card.manager.domain.RolesResourcesExample;
import com.card.manager.domain.Users;
import com.card.manager.domain.UsersExample;
import com.card.manager.services.RoleService;

@Service("RoleServiceImpl")
public class RoleServiceImpl extends MyFrameworkSupperMapper implements RoleService {

	@Override
	public Map<String, Object> loadAllInfo() {
		RolesMapper rolesMapper = this.getMapper(RolesMapper.class);
		ResourcesMapper resourcesMapper = this.getMapper(ResourcesMapper.class);
		UsersMapper usersMapper = this.getMapper(UsersMapper.class);
		
		Map<String, Object> modelMap = new HashMap<String, Object>();  
		List<Roles> tempRoles = rolesMapper.selectByExample(new RolesExample());
		List<Resources> tempResources = resourcesMapper.selectByExample(new ResourcesExample());
		List<Users> tempUsers = usersMapper.selectByExample(new UsersExample());
		
		modelMap.put("users", tempUsers);
		modelMap.put("roles", tempRoles);
		modelMap.put("resources", tempResources);
		
		return modelMap;
	}

	@Override
	public List<Roles> allEnabledList() {
		RolesMapper mapper = this.getMapper(RolesMapper.class);
		RolesExample example = new RolesExample();
		Criteria criteria  = example.createCriteria();
		criteria.andDelflgEqualTo((byte)1);
		criteria.andEnableEqualTo(true);
		List<Roles> list = mapper.selectByExample(example);
		Map<String, Object> modelMap = new HashMap<String, Object>();  
	    return list;
	}

	@Override
	public Set<Roles> getUserRoles(int userid) {
		Set<Roles> set = new HashSet<Roles>();
		RolesMapper mapper = this.getMapper(RolesMapper.class);
		List<Roles> list = mapper.selectRolesForUser(userid);
		if(list != null)
			set.addAll(list);
		return set;
	}

	@Override
	public Map<String, Object> selectRoleForPage(Roles role, PageModel pageModel) {
		RolesMapper mapper = this.getMapper(RolesMapper.class);
		RolesExample example = new RolesExample();
		if(pageModel != null)
			example.setPage(pageModel);
		if(StringUtils.isNotEmpty(pageModel.getSort())) 
			example.setOrderByClause(pageModel.getSort()+" "+pageModel.getOrder());
		Criteria criteria  = example.createCriteria();
		if(StringUtils.isNotBlank(role.getDescs()))
			criteria.andDescsLike("%" + role.getDescs() + "%");
		if(StringUtils.isNotBlank(role.getName()))
			criteria.andNameLike("%" + role.getName() + "%");
		criteria.andDelflgEqualTo((byte)1);
		List<Roles> list = mapper.selectByExample(example);
		Map<String, Object> modelMap = new HashMap<String, Object>();  
	    modelMap.put("total", pageModel.getTotalCount());  
	    modelMap.put("rows", list); 
	    return modelMap;
	}

	@Override
	@Transactional
	public void deleteRoles(final List<Roles> role)
			throws ModifiedByAnotherUserException, Exception {
		batchSubmit(RolesMapper.class,new BatchCallBack() {
			@Override
			public <E> void batchCallBack(E mapper) {
				if(role != null && role.size() > 0) {
					for(Roles a :role){
						a.setDelflg((byte)0);
						((RolesMapper) mapper).updateByPrimaryKeySelective(a);
					}
				}
			}
		});		
	}

	@Override
	@Transactional
	public void addOrUpdate(Roles role) {
		RolesMapper mapper = this.getMapper(RolesMapper.class);
		if(role.getRoleid() == null){
			role.setDelflg((byte)1);
			mapper.insert(role);
		}else{
			mapper.updateByPrimaryKeySelective(role);
		}
	}

	@Override
	public Roles getById(int id) {
		RolesMapper mapper = this.getMapper(RolesMapper.class);
		return mapper.selectByPrimaryKey(id);
	}

	@Override
	@Transactional
	public void add(Roles role) {
		RolesMapper mapper = this.getMapper(RolesMapper.class);
		role.setDelflg((byte)1);
		role.setEnable(true);
		mapper.insert(role);
	}

	@Override
	@Transactional
	public void update(Roles role) {
		RolesMapper mapper = this.getMapper(RolesMapper.class);
		mapper.updateByPrimaryKeySelective(role);
	}

	@Override
	public boolean isExistName(String name) {
		RolesMapper userMapper = this.getMapper(RolesMapper.class);
		RolesExample userExample = new RolesExample();
		userExample.createCriteria().andNameEqualTo(name);
		List<Roles> list = userMapper.selectByExample(userExample);
		if(list == null || list.size() == 0)
			return false;
		else 
			return true;
	}

	@Override
	public List<Resources> getRoleResource(int roleid) {
		ResourcesMapper mapper = this.getMapper(ResourcesMapper.class);
		return mapper.selectResourcesForRole(roleid);
	}

	@Override
	public List<Resources> getAllEnableResource() {
		ResourcesMapper mapper = this.getMapper(ResourcesMapper.class);
		ResourcesExample example = new ResourcesExample();
		example.createCriteria().andEnableEqualTo((byte)1);
		return mapper.selectByExample(example);
	}

	@Override
	@Transactional
	public void saveRoleResource(int roleid, Integer[] resid) {
		RolesResourcesMapper mapper = this.getMapper(RolesResourcesMapper.class);
		RolesResourcesExample example = new RolesResourcesExample();
		example.createCriteria().andRoleidEqualTo(roleid);
		mapper.deleteByExample(example);
		if(resid != null){
			for(Integer id : resid){
				RolesResources rr = new RolesResources();
				rr.setRoleid(roleid);
				rr.setResouceid(id);
				mapper.insert(rr);
			}
		}
	}

	@Override
	public Map<String, Collection<ConfigAttribute>> loadResources() {
		HashMap<String,Collection<ConfigAttribute>> resourceMap = new HashMap<String,Collection<ConfigAttribute>>();
		
		RolesMapper rolesMapper = this.getMapper(RolesMapper.class);
		ResourcesMapper resourcesMapper = this.getMapper(ResourcesMapper.class);
		List<Roles> roles = rolesMapper.selectByExample(new RolesExample());
		for(Roles role : roles){
			List<Resources> resources = resourcesMapper.selectResourcesForRole(role.getRoleid());
			for(Resources resource : resources){
				Collection<ConfigAttribute> configAttributes = null;
				ConfigAttribute configAttribute = new SecurityConfig(role.getName());
				if(resourceMap.containsKey(resource.getUrl())){
					configAttributes = resourceMap.get(resource.getUrl());
					configAttributes.add(configAttribute);
				}else{
					configAttributes = new ArrayList<ConfigAttribute>() ;
					configAttributes.add(configAttribute);
					resourceMap.put(resource.getUrl(), configAttributes);
				}
			}
		}
		
		return resourceMap;
	}

}
